﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Leeder.Logger;
using System.Collections.Concurrent;
using System.Threading;
using NewAndong.Model;

namespace NewAndong.Handle
{
    public class SocketHandler2
    {
        private LogOperate LogObj => Log.GetLogger(this.GetType());
        //第一步：调用socket()函数创建一个用于通信的套接字
        private Socket listenSocket;

        //字典集合：存储IP和Socket的集合
        private Dictionary<string, Socket> OnLineList = new Dictionary<string, Socket>();

        CancellationTokenSource cancel_sendQueue;
        ConcurrentQueue<TcpSendModel> SendQueue;

        //当前时间
        private string CurrentTime
        {
            get { return DateTime.Now.ToString("HH:mm:ss") + Environment.NewLine; }
        }

        //编码格式
        Encoding econding = Encoding.UTF8;

        public void StartService(string ip, int port)
        {
            lockobj = new object();
            //第一步：调用socket()函数创建一个用于通信的套接字
            listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //第二步：给已经创建的套接字绑定一个端口号，这一般通过设置网络套接口地址和调用Bind()函数来实现
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(ip), port);

            try
            {
                listenSocket.Bind(endPoint);
            }
            catch (Exception ex)
            {
                LogObj.Error("服务器开启失败：" + ex.Message);
                return;
            }

            //第三步：调用listen()函数使套接字成为一个监听套接字
            listenSocket.Listen(10);

            LogObj.Info("服务器开启成功");

            SendQueue = new ConcurrentQueue<TcpSendModel>();
            cancel_sendQueue = new CancellationTokenSource();
            LogObj.Info("TCP数据发送线程启动");
            Task.Factory.StartNew(() =>
            {
                Send();
            }, cancel_sendQueue.Token);

            //开启一个线程监听
            Task.Run(new Action(() =>
            {
                ListenConnection();
            }
            ));
        }

        private void ListenConnection()
        {
            while (true)
            {
                Socket clientSocket = listenSocket.Accept();
                string ip = clientSocket.RemoteEndPoint.ToString();
                //更新在线列表
                AddOnLine(ip, true);
                //更新在线列表集合
                OnLineList.Add(ip, clientSocket);
                LogObj.Info(ip + "上线了");
                Task.Run(() => ReceiveMsg(clientSocket));
            }
        }


        /// <summary>
        /// 接收方法
        /// </summary>
        /// <param name="clientSocket"></param>
        private void ReceiveMsg(Socket clientSocket)
        {
            while (true)
            {
                //定义一个2M的缓冲区
                byte[] buffer = new byte[1024 * 1024 * 2];
                int length = -1;
                try
                {
                    length = clientSocket.Receive(buffer);
                }
                catch (Exception)
                {
                    //客户端下线了
                    //更新在线列表
                    string ip = clientSocket.RemoteEndPoint.ToString();
                    AddOnLine(ip, false);
                    OnLineList.Remove(ip);
                    break;
                }

                if (length == 0)
                {
                    //客户端下线了
                    //更新在线列表
                    string ip = clientSocket.RemoteEndPoint.ToString();
                    AddOnLine(ip, false);
                    OnLineList.Remove(ip);
                    break;
                }

                if (length > 0)
                {
                    string info = econding.GetString(buffer, 0, length);
                    if (info == "ping")
                    {
                        //clientSocket.Send(econding.GetBytes("pong"));
                        //AddSendQueue(clientSocket, "pong");
                    }
                    else
                    {
                        LogObj.Debug(DateTime.Now + "TCP接收数据: " + info);
                    }
                }
            }
        }

        /// <summary>
        /// 在线列表更新
        /// </summary>
        /// <param name="clientIp"></param>
        /// <param name="value"></param>
        private void AddOnLine(string clientIp, bool value)
        {

        }

        /// <summary>
        /// 消息发送
        /// </summary>
        public void SendAll(string message)
        {
            foreach (var item in OnLineList)
            {
                AddSendQueue(item.Value, message);
            }
        }

        private async void Send()
        {
            while (!this.cancel_sendQueue.Token.IsCancellationRequested)
            {
                if (!SendQueue.IsEmpty)
                {
                    TcpSendModel result;
                    SendQueue.TryDequeue(out result);
                    if (result != null)
                    {
                        LogObj.Debug(DateTime.Now + "TCP向"+ result.Socket.RemoteEndPoint.ToString() + "发送数据: " + result.Data);
                        result.Socket.Send(econding.GetBytes(result.Data));
                    }
                    await Task.Delay(500);
                }
                else
                {
                    await Task.Delay(1000);
                }
            }
        }

        object lockobj;
        private void AddSendQueue(Socket socket, string data)
        {
            //lock (lockobj)
            //{
            TcpSendModel tcpSendModel = new TcpSendModel();
            tcpSendModel.Data = data;
            tcpSendModel.Socket = socket;
            SendQueue.Enqueue(tcpSendModel);
            //}
        }

    }
}
